package com.kczyjg.hybird

import android.app.Activity
import android.app.ProgressDialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.util.Log
import android.view.KeyEvent
import androidx.core.content.FileProvider
import com.blankj.utilcode.util.AppUtils
import com.blankj.utilcode.util.FileUtils
import com.blankj.utilcode.util.GsonUtils
import com.blankj.utilcode.util.SPUtils
import com.blankj.utilcode.util.ToastUtils
import com.blankj.utilcode.util.ZipUtils
import com.google.gson.reflect.TypeToken
import com.lxj.xpopup.XPopup
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.ceil


object UpdateApkHelper {

    private val H5_VERSION_CODE = "H5_VERSION_CODE"
    private lateinit var mContext: Context
    private lateinit var progressDialog: ProgressDialog
    private var versionInfo: MutableList<VersionData> = mutableListOf()
    fun checkUpdate(context: Context, url: String, callBack: () -> Unit) {
        this.mContext = context
        CoroutineScope(Dispatchers.Main).launch {
            val updateContent = withContext(Dispatchers.IO) {
                try {
                    HttpRequestUtils.get(url)
                } catch (e: Exception) {
                    e.printStackTrace()
                    null
                }
            }
            if (updateContent.isNullOrEmpty()) {
                ToastUtils.showLong("网络异常~")
                return@launch
            }

            val type = object : TypeToken<MutableList<VersionData>>() {}.getType()
            val versionData: MutableList<VersionData> = GsonUtils.fromJson(updateContent, type)
            this@UpdateApkHelper.versionInfo = versionData
            val androidData = versionData.find { it.APPOSNAME == "Android" }
            val appVersionCode = AppUtils.getAppVersionCode()
            if (androidData!!.APPVER > appVersionCode) {
                showAppCheckUpdateDialog(androidData)
                return@launch
            }
            val h5Data = versionData.find { it.APPOSNAME == "SDK_H5" }
            val h5VersionCode = SPUtils.getInstance().getInt(H5_VERSION_CODE)
            if (h5Data!!.APPVER > h5VersionCode) {
                downloadH5(h5Data, callBack)
                return@launch
            }
            callBack()
        }
    }


    fun showAppCheckUpdateDialog(androidData: VersionData) {
        XPopup.Builder(mContext).dismissOnTouchOutside(false)
            .dismissOnBackPressed(false)
            .asConfirm(
                "App更新提示：",
                androidData.UPDATECONTENT,
                "", "更新", {
                    downloadApp(androidData)
                }, {}, true
            )
            .show()
    }

    fun downloadApp(androidData: VersionData) {
        CoroutineScope(Dispatchers.Main).launch {
            val downloadDir: String? = mContext.externalCacheDir?.absolutePath

            val apkFileName = "${androidData.APPNAME}_${androidData.APPVER}.apk"
            val apkFile = File(downloadDir + File.separator + apkFileName)
            apkFile.deleteOnExit()
            showDownProgress("软件更新", "正在下载文件，请稍后")
            withContext(Dispatchers.IO) {
                DownloadManager.getInstance()
                    .download(androidData.APPHTTPPATH, downloadDir, apkFileName, object :
                        DownloadManager.OnDownloadListener {
                        override fun onSuccess(file: File) {
                            CoroutineScope(Dispatchers.Main).launch {
                                //安装
                                installApk(apkFile)
                                if (progressDialog != null && progressDialog.isShowing()) {
                                    progressDialog.dismiss()
                                }
                            }
                        }

                        override fun onProgress(downBytes: Long, totalBytes: Long) {
                            CoroutineScope(Dispatchers.Main).launch {
                                if (progressDialog != null) {
                                    val bytes = downBytes / (1024 * 1024)
                                    val progress = ceil(bytes.toDouble()).toInt()
                                    progressDialog.progress = progress
                                    if (!progressDialog.isShowing) {
                                        val fileSize = totalBytes / (1024 * 1024)
                                        val max = ceil(fileSize.toDouble()).toInt()
                                        progressDialog.max = max
                                        progressDialog.show()
                                    }
                                }
                            }
                        }

                        override fun onFail() {
                            CoroutineScope(Dispatchers.Main).launch {
                                if (progressDialog != null && progressDialog.isShowing) {
                                    progressDialog.dismiss()
                                }
                                apkFile.deleteOnExit()
                            }
                        }
                    })
            }
        }
    }

    fun downloadH5(h5Data: VersionData, callBack: () -> Unit) {
        CoroutineScope(Dispatchers.Main).launch {
            val downloadDir = mContext.externalCacheDir?.absolutePath
            val unzipDir = mContext.cacheDir.absolutePath + File.separator + "h5"
            val h5FileName = "H5_${h5Data.APPVER}.zip"
            val h5File = File(downloadDir + File.separator + h5FileName)
            h5File.deleteOnExit()
            showDownProgress(h5Data.APPNAME, h5Data.UPDATECONTENT)
            withContext(Dispatchers.IO) {
                DownloadManager.getInstance()
                    .download(h5Data.APPHTTPPATH, downloadDir, h5FileName, object :
                        DownloadManager.OnDownloadListener {
                        override fun onSuccess(file: File) {
                            CoroutineScope(Dispatchers.Main).launch {
                                //安装
                                unzip(unzipDir, h5File)
                                SPUtils.getInstance().put(H5_VERSION_CODE, h5Data.APPVER)
                                if (progressDialog != null && progressDialog.isShowing()) {
                                    progressDialog.dismiss()
                                }
                                callBack()
                            }
                        }

                        override fun onProgress(downBytes: Long, totalBytes: Long) {
                            CoroutineScope(Dispatchers.Main).launch {
                                if (progressDialog != null) {
                                    val bytes = downBytes / (1024 * 1024)
                                    val progress = ceil(bytes.toDouble()).toInt()
                                    progressDialog.progress = progress
                                    if (!progressDialog.isShowing) {
                                        val fileSize = totalBytes / (1024 * 1024)
                                        val max = ceil(fileSize.toDouble()).toInt()
                                        progressDialog.max = max
                                        progressDialog.show()
                                    }
                                }
                            }
                        }

                        override fun onFail() {
                            CoroutineScope(Dispatchers.Main).launch {
                                if (progressDialog != null && progressDialog.isShowing) {
                                    progressDialog.dismiss()
                                }
                                h5File.deleteOnExit()
                            }
                        }
                    })
            }
        }
    }

    /**
     * 展示文件下载进度条
     */
    private fun showDownProgress(title: String?, content: String?) {
        //指定UI线程，显示进度条
        progressDialog = ProgressDialog(mContext)
        progressDialog.setCancelable(false) // 必须一直下载完，不可取消
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)
        progressDialog.setMessage(content)
        progressDialog.setProgressNumberFormat("%1d MB /%2d MB")
        progressDialog.setTitle(title)
        progressDialog.setOnKeyListener { dialog: DialogInterface, keyCode: Int, event: KeyEvent -> false }
    }

    fun installApk(apkFile: File) {
        if (!apkFile.exists()) {
            Log.e("InstallApk", "APK file does not exist: ${apkFile.absolutePath}")
            return
        }

        val intent = Intent(Intent.ACTION_VIEW)
        val apkUri: Uri

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // 使用FileProvider
            apkUri = FileProvider.getUriForFile(
                mContext,
                "${BuildConfig.APPLICATION_ID}.fileprovider",
                apkFile
            )
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
        } else {
            // 旧版本直接使用文件路径
            apkUri = Uri.fromFile(apkFile)
        }

        intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

        try {
            mContext.startActivity(intent)
            (mContext as? Activity)?.finish()
        } catch (e: Exception) {
            Log.e("InstallApk", "Failed to install APK: ${e.message}")
            // 可以在这里添加错误处理，比如提示用户
        }
    }

    /**
     * 解压对应的文件
     */
    fun unzip(h5DirPath: String, h5ZipFile: File) {
        try {
            FileUtils.deleteAllInDir(h5DirPath)
            ZipUtils.unzipFile(
                h5ZipFile.absolutePath,
                h5DirPath,
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }

    }

    public fun getVersionInfo(): MutableList<VersionData>{
        return this.versionInfo
    }
}